/**
 * BT.601 和 BT.709 亮度计算公式实现
 * 用于将 RGB 颜色值转换为符合人眼感知的亮度值
 */

export type RgbValue = {
  r: number;
  g: number;
  b: number;
};

export type RgbTuple = [number, number, number];

export interface LumaOptions {
  /**
   * 输入的 RGB 值范围
   * @default '0-255'
   */
  range?: '0-1' | '0-255';
}

/**
 * 使用 BT.601 标准计算亮度值
 * 适用于标清视频 (SDTV)、传统图像设备
 * @param r 红色通道值
 * @param g 绿色通道值
 * @param b 蓝色通道值
 * @param options 计算选项
 * @returns 亮度值 (与输入范围相同)
 */
export function bt601(
  r: number,
  g: number,
  b: number,
  options: LumaOptions = {}
): number {
  const { range = '0-255' } = options;
  
  // 确保输入值在有效范围内
  validateRgbValues(r, g, b, range);
  
  // 如果是 0-255 范围，先转换为 0-1 进行计算
  const rNormalized = range === '0-255' ? r / 255 : r;
  const gNormalized = range === '0-255' ? g / 255 : g;
  const bNormalized = range === '0-255' ? b / 255 : b;
  
  // BT.601 公式: Y = 0.299*R + 0.587*G + 0.114*B
  const lumaNormalized = 0.299 * rNormalized + 0.587 * gNormalized + 0.114 * bNormalized;
  
  // 转换回原始范围
  return range === '0-255' ? Math.round(lumaNormalized * 255) : lumaNormalized;
}

/**
 * 使用 BT.601 标准计算亮度值（接收对象参数）
 * @param rgb RGB 颜色对象
 * @param options 计算选项
 * @returns 亮度值
 */
export function bt601FromObject(
  rgb: RgbValue,
  options?: LumaOptions
): number {
  return bt601(rgb.r, rgb.g, rgb.b, options);
}

/**
 * 使用 BT.601 标准计算亮度值（接收数组参数）
 * @param rgb RGB 颜色数组 [r, g, b]
 * @param options 计算选项
 * @returns 亮度值
 */
export function bt601FromArray(
  rgb: RgbTuple,
  options?: LumaOptions
): number {
  return bt601(rgb[0], rgb[1], rgb[2], options);
}

/**
 * 使用 BT.709 标准计算亮度值
 * 适用于高清视频 (HDTV)、超高清视频 (UHD)、现代显示设备
 * @param r 红色通道值
 * @param g 绿色通道值
 * @param b 蓝色通道值
 * @param options 计算选项
 * @returns 亮度值 (与输入范围相同)
 */
export function bt709(
  r: number,
  g: number,
  b: number,
  options: LumaOptions = {}
): number {
  const { range = '0-255' } = options;
  
  // 确保输入值在有效范围内
  validateRgbValues(r, g, b, range);
  
  // 如果是 0-255 范围，先转换为 0-1 进行计算
  const rNormalized = range === '0-255' ? r / 255 : r;
  const gNormalized = range === '0-255' ? g / 255 : g;
  const bNormalized = range === '0-255' ? b / 255 : b;
  
  // BT.709 公式: Y = 0.2126*R + 0.7152*G + 0.0722*B
  const lumaNormalized = 0.2126 * rNormalized + 0.7152 * gNormalized + 0.0722 * bNormalized;
  
  // 转换回原始范围
  return range === '0-255' ? Math.round(lumaNormalized * 255) : lumaNormalized;
}

/**
 * 使用 BT.709 标准计算亮度值（接收对象参数）
 * @param rgb RGB 颜色对象
 * @param options 计算选项
 * @returns 亮度值
 */
export function bt709FromObject(
  rgb: RgbValue,
  options?: LumaOptions
): number {
  return bt709(rgb.r, rgb.g, rgb.b, options);
}

/**
 * 使用 BT.709 标准计算亮度值（接收数组参数）
 * @param rgb RGB 颜色数组 [r, g, b]
 * @param options 计算选项
 * @returns 亮度值
 */
export function bt709FromArray(
  rgb: RgbTuple,
  options?: LumaOptions
): number {
  return bt709(rgb[0], rgb[1], rgb[2], options);
}

/**
 * 验证 RGB 值是否在指定范围内
 * @param r 红色通道值
 * @param g 绿色通道值
 * @param b 蓝色通道值
 * @param range 范围类型
 */
function validateRgbValues(r: number, g: number, b: number, range: '0-1' | '0-255'): void {
  const min = range === '0-1' ? 0 : 0;
  const max = range === '0-1' ? 1 : 255;
  
  if (r < min || r > max || g < min || g > max || b < min || b > max) {
    throw new Error(`RGB values must be in the ${range} range`);
  }
}

export default {
  bt601,
  bt601FromObject,
  bt601FromArray,
  bt709,
  bt709FromObject,
  bt709FromArray
};
